package com.xxl.job.plus.executor.core;


import com.google.common.base.Charsets;
import org.caffinitas.ohc.CacheSerializer;
import org.caffinitas.ohc.OHCache;
import org.caffinitas.ohc.OHCacheBuilder;

import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;

/**
 * 基于堆外内存的缓存框架 OHC
 * 物理内存=堆外内存+堆内内存。
 * 堆外内存不受堆内内存大小的限制，只受服务器物理内存的大小限制
 */
public class OhcDemo {
    public static void main(String[] args) throws InterruptedException {
        //准备时间，方便观察
        TimeUnit.SECONDS.sleep(10);
        OHCache ohCache = OHCacheBuilder.<String, String>newBuilder()
                .keySerializer(OhcDemo.stringSerializer)
                .valueSerializer(OhcDemo.stringSerializer)
                .capacity(1024L * 1024 * 1024 * 2)
                .build();
        int num = 0;
        while (true) {
            String big = new String(new byte[1024 * 1024]);
            ohCache.put(num + "", big);
            num++;
        }


    }


    public static final CacheSerializer<String> stringSerializer = new CacheSerializer<String>() {
        public void serialize(String s, ByteBuffer buf) {
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            buf.put((byte) ((bytes.length >>> 8) & 0xFF));
            buf.put((byte) ((bytes.length >>> 0) & 0xFF));
            buf.put(bytes);
        }

        public String deserialize(ByteBuffer buf) {
            int length = (((buf.get() & 0xff) << 8) + ((buf.get() & 0xff) << 0));
            byte[] bytes = new byte[length];
            buf.get(bytes);
            return new String(bytes, Charsets.UTF_8);
        }

        public int serializedSize(String s) {
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            // 设置字符串长度限制，2^16 = 65536
//            if (bytes.length > 65535){
//                throw new RuntimeException("encoded string too long: " + bytes.length + " bytes");
//            }
            return bytes.length + 2;
        }
    };

    static int writeUTFLen(String str) {
        int strlen = str.length();
        int utflen = 0;
        int c;

        for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F))
                utflen++;
            else if (c > 0x07FF)
                utflen += 3;
            else
                utflen += 2;
        }

        if (utflen > 65535)
            throw new RuntimeException("encoded string too long: " + utflen + " bytes");

        return utflen + 2;
    }

}